#ifndef __PROCESSPOOL_HPP__
#define __PROCESSPOOL_HPP__

#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"
#include "Channel.hpp"

// typedef std::function<void()> work_t;
using work_t = std::function<void()>;

enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int n, work_t w) : processnum(n), work(w)
    {
    }

    // channel是输出型参数
    // work是回调函数
    int InitProcessPool()
    {
        // 2.创建制定个数的进程
        for (int i = 0; i < processnum; i++)
        {
            // 1.现由管道
            int fds[2];
            int n = pipe(fds);
            if (n == -1)
            {
                return PipeError;
            }

            // 2.创建进程
            pid_t id = fork();
            if (id < 0)
                return ForkError;
            else if (id == 0) // 建立通信的信道
            {
                // 关闭历史的wfd
                std::cout << getpid() << ",child close history fd: ";
                for (auto &c : channels)
                {
                    std::cout << c.Wfd() << " ";
                    c.Close();
                }
                std::cout << "over" << std::endl;

                // child
                ::close(fds[1]); // read
                dup2(fds[0], 0);
                work();
                exit(0);
            }

            // 父进程执行
            ::close(fds[0]); // write
            std::cout << "debug :" << fds[1] << std::endl;
            channels.emplace_back(fds[1], id);
        }

        return OK;
    }

    // 分发任务
    void DispatchTask()
    {
        int who = 0;
        // 2.派发任务
        int num = 5;
        while (num--)
        {
            // 1.选择一个任务，整数
            int task = tm.SelectTask();
            // 2.选择一个子进程：采用轮询
            Channel &curr = channels[who++];
            who %= channels.size();

            std::cout << "#######################" << std::endl;
            std::cout << "send" << task << "to" << curr.Name() << ",任务还剩：" << num << std::endl;
            std::cout << "########################" << std::endl;

            // 3.派发任务
            curr.Send(task);

            sleep(1);
        }
    }

    void CleanProcessPool()
    {
        for (auto &c : channels)
        {
            c.Close();
            pid_t rid = waitpid(c.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child: " << rid << "wait....success" << std::endl;
            }
        }
    }

    void DebugPrint()
    {
        for (auto &c : channels)
        {
            std::cout << c.Name() << std::endl;
        }
    }

    ~ProcessPool()
    {
    }

private:
    std::vector<Channel> channels; // 保存的是master打开的所有写端
    int processnum;
    work_t work;
};

#endif
